#pragma once

#define CLASS_STRUCTS_VERSION 4
#include "other.hpp"

struct SimGroup;

//0 + 52 bytes
#define ClassStruct_SimObject \
	void* vftable; \
	const char* objectName; \
	SimObject* nextNameObject; \
	SimObject* nextManagerNameObject; \
	SimObject* nextIdObject; \
	SimGroup* mGroup; \
	U32 mFlags; \
	Notify* mNotifyList; \
	U32 id; /* +32 */ \
	Namespace* mNamespace; /* +36 */ \
	unsigned int mTypeMask; \
	void* SimObject_0[1]; \
	void* mFieldDictionary; \

struct SimObject
{
	ClassStruct_SimObject
};



//52 + 12 bytes
#define ClassStruct_SimSet \
	U32 mElementCount; /* +52 */ \
	U32 mArraySize; /* +56 */ \
	SimObject* (*mArray)[]; /* +60 */ \

struct SimSet
{
	ClassStruct_SimObject
	ClassStruct_SimSet
};



//Not known to have any member fields
//64 + ? bytes
#define ClassStruct_SimGroup \

struct SimGroup
{
	ClassStruct_SimObject
	ClassStruct_SimSet
	ClassStruct_SimGroup
};


/* More complicated multi-inherit NetConnection class */
#include "ClassStructsConnProtocol.hpp"


//52 + 28 bytes
#define ClassStruct_NetObject \
	void* NetObject_0[4]; \
	int netFlags; /* +68 */ \
	int ghostID; /* +72 */ \
	void* NetObject_1[1]; \

struct NetObject
{
	ClassStruct_SimObject
	ClassStruct_NetObject
};



//80 + n bytes
#define ClassStruct_Sun \
	void* Sun_0[7]; \
	float DirectLightR; /* +108 */ \
	float DirectLightG; \
	float DirectLightB; \
	float DirectLightA; /* unused */ \
	float AmbientLightR; /* +124 */ \
	float AmbientLightG; \
	float AmbientLightB; \
	float AmbientLightA; /* unused */ \
	void* Sun_1[2]; \
	float Azimuth_Readonly1; /* +148 */ \
	float Elevation_Readonly1; /* + 152 */ \
	float Azimuth_Readonly2; /* +156 */ \
	float Elevation_Readonly2; /* +160 */ \
	void* Sun_2[8]; \
	float ShadowColorR; /* +196 */ \
	float ShadowColorG; \
	float ShadowColorB; \
	float ShadowColorA; /* unused */ \

struct Sun
{
	ClassStruct_SimObject
	ClassStruct_NetObject
	ClassStruct_Sun
};




//80 + 408 bytes
#define ClassStruct_SceneObject \
	void* SceneObject_0[3]; \
	MatrixF mObjToWorld; /* +92 */ \
	MatrixF mWorldToObj; /* +156 */ \
	Point3F mObjScale; /* +220 ; not always authoritative */ \
	void* SceneObject_1[64]; \

struct SceneObject
{
	ClassStruct_SimObject
	ClassStruct_NetObject
	ClassStruct_SceneObject
};




//488 + 28 bytes
#define ClassStruct_GameBase \
	void* GameBase_0[7]; \

struct GameBase
{
	ClassStruct_SimObject
	ClassStruct_NetObject
	ClassStruct_SceneObject
	ClassStruct_GameBase
};



//516 + 1300 bytes
#define ClassStruct_ShapeBase \
	void* ShapeBase_0[237]; \
	U32 shapeName_netStringID; /* +1468 ; can be used with NetStringTable::lookupString (0x59adc0) */ \
	void* ShapeBase_1[87]; \

struct ShapeBase
{
	ClassStruct_SimObject
	ClassStruct_NetObject
	ClassStruct_SceneObject
	ClassStruct_GameBase
	ClassStruct_ShapeBase
};



//1816 + 780 bytes
#define ClassStruct_Player \
	void* Player_0[195]; \

struct Player
{
	ClassStruct_SimObject
	ClassStruct_NetObject
	ClassStruct_SceneObject
	ClassStruct_GameBase
	ClassStruct_ShapeBase
	ClassStruct_Player
};



//2596 + 140 bytes
#define ClassStruct_AIPlayer \
	void* AIPlayer_0[35]; \

struct AIPlayer
{
	ClassStruct_SimObject
	ClassStruct_NetObject
	ClassStruct_SceneObject
	ClassStruct_GameBase
	ClassStruct_ShapeBase
	ClassStruct_Player
	ClassStruct_AIPlayer
};



//52 + 28(?) bytes
#define ClassStruct_TCPObject \
	void* TCPObject_00; \
	void* TCPObject_01; \
	void* TCPObject_02; \
	void* TCPObject_03; \
	void* TCPObject_04; \
	void* TCPObject_05; \
	void* TCPObject_06; \

struct TCPobject
{
	ClassStruct_SimObject
	ClassStruct_TCPObject
};



//80 + ??
#define ClassStruct_SOCKobject \

struct SOCKobject
{
	ClassStruct_SimObject
	ClassStruct_TCPObject
	ClassStruct_SOCKobject
};



//80 + ??
#define ClassStruct_HTTPObject \

struct HTTPobject
{
	ClassStruct_SimObject
	ClassStruct_TCPObject
	ClassStruct_HTTPObject
};


int NamespaceClasses_instanceOf(SimObject* obj, const char* className)
{
	if(obj == NULL)
		return -1;

	Namespace* ns = obj->mNamespace;
	for(int i = 0; ns != NULL; i++)
	{
		//Look for names of real classes
		if(ns->mClassRep != NULL)
			if(strcmp(className, ns->mName) == 0)
				return 1;

		ns = ns->mParent;
	}

	return 0;
}

const char* NamespaceClasses_getClassName(SimObject* obj)
{
	if(obj == NULL)
		return "";

	Namespace* ns = obj->mNamespace;
	for(int i = 0; ns != NULL; i++)
	{
		//Look for names of real classes
		if(ns->mClassRep != NULL)
			return ns->mName;

		ns = ns->mParent;
	}

	return "";
}

